/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.nifi.processor;

import org.apache.nifi.controller.queue.QueueSize;
import org.apache.nifi.flowfile.FlowFile;
import org.apache.nifi.processor.exception.FlowFileAccessException;
import org.apache.nifi.processor.exception.FlowFileHandlingException;
import org.apache.nifi.processor.exception.MissingFlowFileException;
import org.apache.nifi.processor.exception.ProcessException;
import org.apache.nifi.processor.io.InputStreamCallback;
import org.apache.nifi.processor.io.OutputStreamCallback;
import org.apache.nifi.processor.io.StreamCallback;
import org.apache.nifi.provenance.ProvenanceReporter;

import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Path;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;

/**
 * <p>
 * A process session encompasses all the behaviors a processor can perform to 封装了Processor对FlowFile的原子操作
 * obtain, clone, read, modify remove FlowFiles in an atomic unit. A process 获取,克隆,读取,修改,移除。ProcessorSession
 * session is always tied to a single processor at any one time and ensures no 在任何时候,总是与某个processor绑定在一起,
 * FlowFile can ever be accessed by any more than one processor at a given time. 保证FlowFile在任何时候,不会被其他任意的processor访问。
 * The session also ensures that all FlowFiles are always accounted for. The
 * creator of a ProcessSession is always required to manage the session. //session由其创建者管理。
 * </p>
 *
 * <p>
 * A session is not considered thread safe. The session supports a unit of work //session不是线程安全的。
 * that is either committed or rolled back //session支持的操作要么是确认,要么是回滚。
 * </p>
 *
 * <p>
 * As noted on specific methods and for specific exceptions automated rollback  在某些特别的方法上,当特别的异常发生时,
 * will occur to ensure consistency of the repository. However, several 会自动回滚来保证仓库的一致性。然而,在有些场景中
 * situations can result in exceptions yet not cause automated rollback. In 会发生不会自动回滚的异常。
 * these cases the consistency of the repository will be retained but callers 在这些场景中,仓库的一致性还是有保证的(这是什么意思?)
 * will be able to indicate whether it should result in rollback or continue on 由调用方来决定是回滚还是确认。
 * toward a commit.
 * </p>
 *
 * <p>
 * A process session has two 'terminal' methods that will result in the process session //process session有两个"终结"方法,会导致session回到最初的状态,
 * being in a 'fresh', containing no knowledge or any FlowFile, as if the session were newly 不包含任何信息或者FlowFile,就像这个session是刚刚创建的一样。
 * created. After one of these methods is called, the instance may be used again. The terminal 这些方法的其中之一调用后,实例又可以使用了。
 * methods for a Process Session are the {@link #commit()} and {@link #rollback()}. Additionally, 这两个终结方法是commit和rollback。此外
 * the {@link #migrate(ProcessSession, Collection)} method results in {@code this} containing 方法migrate,会使得当前实例对之前的FlowFile一无所知,
 * no knowledge of any of the FlowFiles that are provided, as if the FlowFiles never existed in 就像这些FlowFile从来没有在这个session中出现过。
 * this ProcessSession. After each commit or rollback, the session can be used again. Note, however, 每一确认或者回滚之后,这个会话都可以重用。然而,需要注意
 * that even if all FlowFiles are migrated via the {@link #migrate(ProcessSession, Collection)} method, 即使所有的FlowFile通过migrate方法转移了,
 * this Process Session is not entirely cleared, as it still has knowledge of Counters that were adjusted //session实例不是完全干净的,因为还有通过adjustCounter方法调整的Counters。
 * via the {@link #adjustCounter(String, long, boolean)} method. A commit or rollback will clear these 确认或者回滚方法也会清理这些计数器。
 * counters, as well.
 * </p>
 */
public interface ProcessSession {

    /**
     * <p>
     * Commits the current session ensuring all operations against FlowFiles 确认当前会话,保证在当前会话中所有对FlowFiles的操作
     * within this session are atomically persisted. All FlowFiles operated on 都能原子得持久化(怪怪的)。这个会话中的所有FlowFiles
     * within this session must be accounted for by transfer or removal or the 要么转移走(发到某个relationship对应的额connection),要移除,否则确认失败。
     * commit will fail.</p>
     *
     * <p>
     * As soon as the commit completes the session is again ready to be used</p> 一旦确认操作完成,会话可以重用了。
     *
     * @throws IllegalStateException if detected that this method is being 在当前会话中另一个方法的回调中调用,产生这个异常。
     * called from within a callback of another method in this session.
     * @throws FlowFileHandlingException if not all FlowFiles acted upon within
     * this session are accounted for by user code such that they have a
     * transfer identified or where marked for removal. Automated rollback
     * occurs.
     * @throws ProcessException if some general fault occurs while persisting
     * the session. Initiates automatic rollback. The root cause can be obtained
     * via <code>Exception.getCause()</code>
     */
    void commit();

    /**
     * Reverts any changes made during this session. All FlowFiles are restored 撤销会话中的所有修改。所有FlowFile的状态都恢复成
     * back to their initial session state and back to their original queues. If 初始的状态,并回到原始队列。如果确认或者回滚已经发生,
     * this session is already committed or rolled back then no changes will 那么不会发生任何改变。
     * occur. This method can be called any number of times. Calling this method 这个方法可以被调用任意次数。这方法与rollback(false)等价。
     * is identical to calling {@link #rollback(boolean)} passing
     * <code>false</code> as the parameter.
     */
    void rollback();

    /**
     * Reverts any changes made during this session. All FlowFiles are restored
     * back to their initial session state and back to their original queues, 惩罚是发生在,恢复操作之前?
     * after optionally being penalized. If this session is already committed or
     * rolled back then no changes will occur. This method can be called any
     * number of times.
     *
     * @param penalize whether or not the FlowFiles that are being restored back 是否惩罚这些需要恢复的FlowFiles。
     * to their queues should be penalized
     */
    void rollback(boolean penalize);

    /**
     * <p>
     * Migrates ownership of the given FlowFiles from {@code this} to the given {@code newOwner}.
     * </p> 将指定FlowFiles的所有关系从当前会话转给指定的新会话。
     *
     * <p>
     * When calling this method, all of the following pre-conditions must be met:
     * </p> 调用这个方法时,必须满足下面的所有前提条件:
     *
     * <ul>
     * <li>This method cannot be called from within a callback 这个方法不能在回调函数中调用
     * (see {@link #write(FlowFile, OutputStreamCallback)}, {@link #write(FlowFile, StreamCallback)},
     * {@link #read(FlowFile, InputStreamCallback)}, {@link #read(FlowFile, boolean, InputStreamCallback)} for any of
     * the given FlowFiles.</li>
     * <li>No InputStream can be open for the content of any of the given FlowFiles (see {@link #read(FlowFile)}).</li> 不能打开给定的FlowFiles的输入流
     * <li>Each of the FlowFiles provided must be the most up-to-date copy of the FlowFile.</li>每个FlowFiles必须是该FlowFile的最新版本
     * <li>For any provided FlowFile, if the FlowFile has any child (e.g., by calling {@link #create(FlowFile)} and passing the FlowFile
     * as the argument), then all children that were created must also be in the Collection of provided FlowFiles.</li>
     * </ul> 对于任一提供的FlowFile,如果某个FlowFile有子FlowFile,并且传递了该FlowFile,那么所有创建的子FlowFile必须包含在提供的FlowFile集合中。
     *
     * @param newOwner the ProcessSession that is to become the new owner of all FlowFiles
     *            that currently belong to {@code this}.
     * @param flowFiles the FlowFiles to migrate
     */
    void migrate(ProcessSession newOwner, Collection<FlowFile> flowFiles);

    /**
     * Adjusts counter data for the given counter name and takes care of 调整给定名字的计数器,处理未注册的计数器。
     * registering the counter if not already present. The adjustment occurs 这种调整只会发生在确认会话时。
     * only if and when the ProcessSession is committed.
     *
     * @param name the name of the counter 计数器名
     * @param delta the delta by which to modify the counter (+ or -) 需要调整的值
     * @param immediate if true, the counter will be updated immediately, 如果为true,不管有没有确认或者回滚,立即更新计数器;
     *            without regard to whether the ProcessSession is commit or rolled back; 否则只有在确认时才调整。
     *            otherwise, the counter will be incremented only if and when the
     *            ProcessSession is committed.
     */
    void adjustCounter(String name, long delta, boolean immediate);

    /**
     * @return FlowFile that is next highest priority FlowFile to process. 返回下一个需要处理的优先级最高的FlowFile。
     * Otherwise returns null. 否则返回null。
     */
    FlowFile get();

    /**
     * Returns up to <code>maxResults</code> FlowFiles from the work queue. If 从工作队列中返回最多maxResults个FlowFiles。
     * no FlowFiles are available, returns an empty list. Will not return null. 如果没有可用的FlowFiles,返回一个空列表,而非null。
     * If multiple incoming queues are present, the behavior is unspecified in 如果有多个输入队列,单词调用是从所有的队列中还是某个队列中
     * terms of whether all queues or only a single queue will be polled in a 获取FlowFile没有定义。
     * single call.
     *
     * @param maxResults the maximum number of FlowFiles to return
     * @return up to <code>maxResults</code> FlowFiles from the work queue. If
     * no FlowFiles are available, returns an empty list. Will not return null.
     * @throws IllegalArgumentException if <code>maxResults</code> is less than
     * 0
     */
    List<FlowFile> get(int maxResults);

    /**
     * <p>
     * Returns all FlowFiles from all of the incoming queues for which the given 从所有的输入队列中,返回满足FlowFileFilter的
     * {@link FlowFileFilter} indicates should be accepted. Calls to this method 的所有FlowFile。对这个方法的调用是排他访问
     * provide exclusive access to the underlying queues. I.e., no other thread 底层队列的。例如,不允许其他的线程从处理器的队列中
     * will be permitted to pull FlowFiles from this Processor's queues or add 获取FlowFiles 或者 添加FlowFile到底层队列,直到
     * FlowFiles to this Processor's incoming queues until this method call has 这个方法调用结束。
     * returned.
     * </p>
     *
     * @param filter to limit which flow files are returned
     * @return all FlowFiles from all of the incoming queues for which the given
     * {@link FlowFileFilter} indicates should be accepted.
     */
    List<FlowFile> get(FlowFileFilter filter);

    /**
     * @return the QueueSize that represents the number of FlowFiles and their 返回的QueueSize表明了FlowFiles的个数,以及
     * combined data size for all FlowFiles waiting to be processed by the 持有这个会话的Processor需要处理的所有FlowFile的数据大小
     * Processor that owns this ProcessSession, regardless of which Connection
     * the FlowFiles live on
     */
    QueueSize getQueueSize();

    /**
     * Creates a new FlowFile in the repository with no content and without any 在仓库中创建一个新的FlowFile,它没有内容
     * linkage to a parent FlowFile. This method is appropriate only when data 也没有相关的父FlowFile。这个方法只适用于
     * is received or created from an external system. Otherwise, this method 从外部系统中接收或者创建数据。其他场景中,
     * should be avoided and should instead use {@link #create(FlowFile)} or 避免使用该方法,应该使用create(FlowFile)
     * {@see #create(Collection)}. 或者create(Collection)
     *
     * When this method is used, a Provenance CREATE or RECEIVE Event should be 当使用这个方法时,应该产生CREATE或者RECEIVE事件
     * generated. See the {@link #getProvenanceReporter()} method and
     * {@link ProvenanceReporter} class for more information
     *
     * @return newly created FlowFile
     */
    FlowFile create();

    /**
     * Creates a new FlowFile in the repository with no content but with a 在仓库中创建一个没有内容FlowFile,当是有父FlowFile。
     * parent linkage to <code>parent</code>. The newly created FlowFile will 新建的FlowFile会继承所有的父属性,除了UUID。
     * inherit all of the parent's attributes except for the UUID. This method 这个方法会根据在会话确认之前,
     * will automatically generate a Provenance FORK event or a Provenance JOIN 是否从同一个父FlowFile产生其他的FlowFile,
     * event, depending on whether or not other FlowFiles are generated from the 自动生成一个FORK事件或者JOIN事件。
     * same parent before the ProcessSession is committed.
     *
     * @param parent to base the new flowfile on
     * @return newly created flowfile
     */
    FlowFile create(FlowFile parent);

    /**
     * Creates a new FlowFile in the repository with no content but with a 在仓库中创建一个没有内容FlowFile,当是有一组父FlowFile。
     * parent linkage to the FlowFiles specified by the parents Collection. The
     * newly created FlowFile will inherit all of the attributes that are in 新建的FlowFile会继承所有的公共父属性,除了UUID
     * common to all parents (except for the UUID, which will be in common if
     * only a single parent exists). This method will automatically generate a 这个方法会自动产生一个JOIN事件。
     * Provenance JOIN event.
     *
     * @param parents which the new flowfile should inherit shared attributes from
     * @return new flowfile
     */
    FlowFile create(Collection<FlowFile> parents);

    /**
     * Creates a new FlowFile that is a clone of the given FlowFile as of the 创建指定FlowFile的克隆,包含内容和属性。
     * time this is called, both in content and attributes. This method 这个方法会自动产生一个CLONE事件。
     * automatically emits a Provenance CLONE Event.
     *
     * @param example FlowFile to be the source of cloning - given FlowFile must
     * be a part of the given session
     * @return FlowFile that is a clone of the given example
     * @throws IllegalStateException if detected that this method is being
     * called from within a callback of another method in this session and for
     * the given FlowFile(s)
     * @throws FlowFileHandlingException if the given FlowFile is already
     * transferred or removed or doesn't belong to this session. Automatic
     * rollback will occur.
     * @throws MissingFlowFileException if the given FlowFile content cannot be
     * found. The FlowFile should no longer be reference, will be internally
     * destroyed, and the session is automatically rolled back and what is left
     * of the FlowFile is destroyed.
     * @throws FlowFileAccessException if some IO problem occurs accessing
     * FlowFile content
     * @throws NullPointerException if the argument null
     */
    FlowFile clone(FlowFile example);

    /**
     * Creates a new FlowFile whose parent is the given FlowFile. The content of 创建一个新的FlowFile,其父是给定的FlowFile。
     * the new FlowFile will be a subset of the byte sequence of the given 新建的FlowFile的内容是给定FlowFile的字节序列根据
     * FlowFile starting at the specified offset and with the length specified. 给定的偏移和长度确定的子集。
     * The new FlowFile will contain all of the attributes of the original. This 新的FlowFile会包含所有的属性。
     * method automatically emits a Provenance FORK Event (or a Provenance CLONE 这个方法会自动产生一个FORK事件(或者CLONE事件
     * Event, if the offset is 0 and the size is exactly equal to the size of 如果偏移量是0,长度与给定FlowFile的长度一致时。)
     * the example FlowFile).
     *
     * @param parent to base the new flowfile attributes on
     * @param offset of the parent flowfile to base the child flowfile content on
     * @param size of the new flowfile from the offset
     * @return a FlowFile with the specified size whose parent is first argument
     * to this function
     *
     * @throws IllegalStateException if detected that this method is being
     * called from within a callback of another method in this session and for
     * the given FlowFile
     * @throws FlowFileHandlingException if the given FlowFile is already
     * transferred or removed or doesn't belong to this session, or if the
     * specified offset + size exceeds that of the size of the parent FlowFile.
     * Automatic rollback will occur.
     * @throws MissingFlowFileException if the given FlowFile content cannot be
     * found. The FlowFile should no longer be reference, will be internally
     * destroyed, and the session is automatically rolled back and what is left
     * of the FlowFile is destroyed.
     */
    FlowFile clone(FlowFile parent, long offset, long size);

    /**
     * Sets a penalty for the given FlowFile which will make it unavailable to 惩罚给定的FlowFile,在惩罚期内,不能操作制定的FlowFile。
     * be operated on any further during the penalty period.
     *
     * @param flowFile to penalize
     * @return FlowFile the new FlowFile reference to use
     * @throws IllegalStateException if detected that this method is being
     * called from within a callback of another method in this session and for
     * the given FlowFile(s)
     * @throws FlowFileHandlingException if the given FlowFile is already
     * transferred or removed or doesn't belong to this session. Automatic
     * rollback will occur.
     * @throws NullPointerException if the argument null
     */
    FlowFile penalize(FlowFile flowFile);

    /**
     * Updates the given FlowFiles attributes with the given key/value pair. If 使用给定的一组键值对更新FlowFile的属性。
     * the key is named {@code uuid}, this attribute will be ignored. 如果键是uuid,忽略。
     *
     * @param flowFile to update
     * @param key of attribute
     * @param value of attribute
     * @return FlowFile the updated FlowFile
     * @throws FlowFileHandlingException if the given FlowFile is already
     * transferred or removed or doesn't belong to this session. Automatic
     * rollback will occur.
     * @throws NullPointerException if an argument is null
     */
    FlowFile putAttribute(FlowFile flowFile, String key, String value);

    /**
     * Updates the given FlowFiles attributes with the given key/value pairs. If 使用给定的一些列键值对,更新FlowFile的属性。
     * the map contains a key named {@code uuid}, this attribute will be 如果包含uuid,忽略。
     * ignored.
     *
     * @param flowFile to update
     * @param attributes the attributes to add to the given FlowFile
     * @return FlowFile the updated FlowFile
     * @throws IllegalStateException if detected that this method is being
     * called from within a callback of another method in this session and for
     * the given FlowFile(s)
     * @throws FlowFileHandlingException if the given FlowFile is already
     * transferred or removed or doesn't belong to this session. Automatic
     * rollback will occur.
     * @throws NullPointerException if an argument is null
     */
    FlowFile putAllAttributes(FlowFile flowFile, Map<String, String> attributes);

    /**
     * Removes the given FlowFile attribute with the given key. If the key is
     * named {@code uuid}, this method will return the same FlowFile without
     * removing any attribute.
     *
     * @param flowFile to update
     * @param key of attribute
     * @return FlowFile the updated FlowFile
     * @throws IllegalStateException if detected that this method is being
     * called from within a callback of another method in this session and for
     * the given FlowFile(s)
     * @throws FlowFileHandlingException if the given FlowFile is already
     * transferred or removed or doesn't belong to this session. Automatic
     * rollback will occur.
     * @throws NullPointerException if the argument null
     */
    FlowFile removeAttribute(FlowFile flowFile, String key);

    /**
     * Removes the attributes with the given keys from the given FlowFile. If
     * the set of keys contains the value {@code uuid}, this key will be ignored
     *
     * @param flowFile to update
     * @param keys of attribute
     * @return FlowFile the updated FlowFile
     * @throws IllegalStateException if detected that this method is being
     * called from within a callback of another method in this session and for
     * the given FlowFile(s)
     * @throws FlowFileHandlingException if the given FlowFile is already
     * transferred or removed or doesn't belong to this session. Automatic
     * rollback will occur.
     * @throws NullPointerException if the argument null
     */
    FlowFile removeAllAttributes(FlowFile flowFile, Set<String> keys);

    /**
     * Remove all attributes from the given FlowFile that have keys which match
     * the given pattern. If the pattern matches the key {@code uuid}, this key
     * will not be removed.
     *
     * @param flowFile to update
     * @param keyPattern may be null; if supplied is matched against each of the
     * FlowFile attribute keys
     * @return FlowFile containing only attributes which did not meet the key
     * pattern
     */
    FlowFile removeAllAttributes(FlowFile flowFile, Pattern keyPattern);

    /**
     * Transfers the given FlowFile to the appropriate destination processor 根据给定的relationship，将FlowFile转移到适当的目标处理器队列
     * work queue(s) based on the given relationship. If the relationship leads 如果这个relationship，对应不止一个目标，
     * to more than one destination the state of the FlowFile is replicated such 复制FlowFile的状态，
     * that each destination receives an exact copy of the FlowFile though each 这样每一个目标都会接收到一个具有唯一ID的FlowFile副本。
     * will have its own unique identity. The destination processors will not be 在会话得到确认或者
     * able to operate on the given FlowFile until this session is committed or 会话转移到其他处理器之前，
     * until the ownership of the session is migrated to another processor. If 目标处理器不能操作给定的FlowFile。
     * ownership of the session is passed to a destination processor then that 如果会话的所有关系传递给了目标处理器，
     * destination processor will have immediate visibility of the transferred 那么属于该会话的所有FlowFile对于目标处理器立即变得可见。
     * FlowFiles within the session.
     *
     * @param flowFile to transfer
     * @param relationship to transfer to
     * @throws IllegalStateException if detected that this method is being 在当前会话中另一个方法的回调函数中调用
     * called from within a callback of another method in this session and for
     * the given FlowFile(s)
     * @throws FlowFileHandlingException if the given FlowFile is already 给定的FlowFile已经转移了或者移除了或者不属于这个会话。
     * transferred or removed or doesn't belong to this session. Automatic 自动回滚。
     * rollback will occur.
     * @throws NullPointerException if the argument null 参数是null
     * @throws IllegalArgumentException if given relationship is not a known or 给定的relationship未知或者未注册
     * registered relationship
     */
    void transfer(FlowFile flowFile, Relationship relationship);

    /**
     * Transfers the given FlowFile back to the work queue from which it was 将给定的FlowFile转回到从中获取他们的队列。
     * pulled. The processor will not be able to operate on the given FlowFile 直到会话确认,处理器是服务操作这写FlowFiles的。
     * until this session is committed. Any modifications that have been made to 对FlowFile的修改会保持。
     * the FlowFile will be maintained. FlowFiles that are created by the 无法通过这个方法,将处理器自己创建的FlowFile转回去。
     * processor cannot be transferred back to themselves via this method.
     *
     * @param flowFile to transfer
     * @throws IllegalStateException if detected that this method is being
     * called from within a callback of another method in this session and for
     * the given FlowFile(s)
     * @throws FlowFileHandlingException if the given FlowFile is already
     * transferred or removed or doesn't belong to this session. Automatic
     * rollback will occur.
     * @throws IllegalArgumentException if the FlowFile was created by this
     * processor
     * @throws NullPointerException if the argument null
     */
    void transfer(FlowFile flowFile);

    /**
     * Transfers the given FlowFiles back to the work queues from which the 将给定的FlowFiles转回到从中获取他们的队列。
     * FlowFiles were pulled. The processor will not be able to operate on the 直到会话确认,处理器是服务操作这写FlowFiles的。
     * given FlowFile until this session is committed. Any modifications that 对FlowFile的修改会保持。
     * have been made to the FlowFile will be maintained. FlowFiles that are 无法通过这个方法,将处理器自己创建的FlowFile转回去。
     * created by the processor cannot be transferred back to themselves via
     * this method.
     *
     * @param flowFiles to transfer
     * @throws IllegalStateException if detected that this method is being
     * called from within a callback of another method in this session and for
     * the given FlowFile(s)
     * @throws FlowFileHandlingException if the given FlowFiles are already
     * transferred or removed or don't belong to this session. Automatic
     * rollback will occur.
     * @throws IllegalArgumentException if the FlowFile was created by this
     * processor
     * @throws NullPointerException if the argument null
     */
    void transfer(Collection<FlowFile> flowFiles);

    /**
     * Transfers the given FlowFile to the appropriate destination processor 根据给定的relationship,将给定的FlowFiles转移到
     * work queue(s) based on the given relationship. If the relationship leads 合适的目标处理器队列。如果relationship对应
     * to more than one destination the state of the FlowFile is replicated such 不止一个目标,复制FlowFile的状态,
     * that each destination receives an exact copy of the FlowFile though each 这样每一个目标都会收到一个副本,
     * will have its own unique identity. The destination processors will not be 但是有自己的唯一标识。在会话得到确认或者
     * able to operate on the given FlowFile until this session is committed or 会话的所属关系迁移到其他处理器之前,目标处理器
     * until the ownership of the session is migrated to another processor. If 无法操作给定的FlowFile。如果会话的所属关系转移
     * ownership of the session is passed to a destination processor then that 到了目标处理器,那么会话中转移的FlowFiles对于
     * destination processor will have immediate visibility of the transferred 目标处理器来说变得即刻可见。
     * FlowFiles within the session.
     *
     * @param flowFiles to transfer
     * @param relationship to transfer to
     * @throws IllegalStateException if detected that this method is being
     * called from within a callback of another method in this session and for
     * the given FlowFile(s)
     * @throws FlowFileHandlingException if the given FlowFile is already
     * transferred or removed or doesn't belong to this session. Automatic
     * rollback will occur.
     * @throws NullPointerException if the argument null
     * @throws IllegalArgumentException if given relationship is not a known or
     * registered relationship
     */
    void transfer(Collection<FlowFile> flowFiles, Relationship relationship);

    /**
     * Ends the managed persistence for the given FlowFile. The persistent 结束对给定FlowFile的管理。
     * attributes for the FlowFile are deleted and so is the content assuming 删除持久属性和内容。
     * nothing else references it and this FlowFile will no longer be available 假设没有人引用这个FlowFile,
     * for further operation. 对这个FlowFile的后续操作也变得不可用。
     *
     * @param flowFile to remove
     * @throws IllegalStateException if detected that this method is being
     * called from within a callback of another method in this session and for
     * the given FlowFile(s)
     * @throws FlowFileHandlingException if the given FlowFile is already
     * transferred or removed or doesn't belong to this session. Automatic
     * rollback will occur.
     */
    void remove(FlowFile flowFile);

    /**
     * Ends the managed persistence for the given FlowFiles. The persistent 结束对给定FlowFiles的管理。删除它的
     * attributes for the FlowFile are deleted and so is the content assuming 持久属性和内容。
     * nothing else references it and this FlowFile will no longer be available
     * for further operation.
     *
     * @param flowFiles to remove
     * @throws IllegalStateException if detected that this method is being
     * called from within a callback of another method in this session and for
     * the given FlowFile(s)
     * @throws FlowFileHandlingException if any of the given FlowFile is already
     * transferred or removed or doesn't belong to this session. Automatic
     * rollback will occur.
     */
    void remove(Collection<FlowFile> flowFiles);

    /**
     * Executes the given callback against the contents corresponding to the 在给定的FlowFile上执行指定的回调函数
     * given FlowFile.
     *
     * @param source flowfile to retrieve content of 从中获取内容的FlowFile
     * @param reader that will be called to read the flowfile content 调用reader来读取flowfile的内容
     * @throws IllegalStateException if detected that this method is being
     *             called from within a callback of another method in this session and for
     *             the given FlowFile(s)
     * @throws FlowFileHandlingException if the given FlowFile is already
     *             transferred or removed or doesn't belong to this session. Automatic
     *             rollback will occur.
     * @throws MissingFlowFileException if the given FlowFile content cannot be
     *             found. The FlowFile should no longer be referenced, will be internally
     *             destroyed, and the session is automatically rolled back and what is left
     *             of the FlowFile is destroyed.
     * @throws FlowFileAccessException if some IO problem occurs accessing
     *             FlowFile content; if an attempt is made to access the InputStream
     *             provided to the given InputStreamCallback after this method completed its
     *             execution
     */
    void read(FlowFile source, InputStreamCallback reader) throws FlowFileAccessException;

    /**
     * Provides an InputStream that can be used to read the contents of the given FlowFile. 返回一个可以读取指定FlowFile内容的InputStream。
     * This method differs from those that make use of callbacks in that this method returns 这个方法有别与那些使用回调函数的方法,它会返回
     * an InputStream and expects the caller to properly handle the lifecycle of the InputStream 一个InputStream,并且它的生命周期由调用方妥善处理
     * (i.e., the caller is responsible for ensuring that the InputStream is closed appropriately). (即,调用方要负责保证正确的关闭InputStream)。
     * The Process Session may or may not handle closing the stream when {@link #commit()} or {@link #rollback()} 会话在调用commit或者rollback的时候可能会也可能不会关闭流,
     * is called, but the responsibility of doing so belongs to the caller. The InputStream will throw 但是关闭的责任是属于调用方的。在会话确认或者回滚之后,
     * an IOException if an attempt is made to read from the stream after the session is committed or 尝试从数据流中读数据会抛IOException异常。
     * rolled back.
     *
     * @param flowFile the FlowFile to read
     * @return an InputStream that can be used to read the contents of the FlowFile
     * @throws IllegalStateException if detected that this method is being
     *             called from within a callback of another method in this session and for
     *             the given FlowFile(s)
     * @throws FlowFileHandlingException if the given FlowFile is already
     *             transferred or removed or doesn't belong to this session. Automatic
     *             rollback will occur.
     * @throws MissingFlowFileException if the given FlowFile content cannot be
     *             found. The FlowFile should no longer be referenced, will be internally
     *             destroyed, and the session is automatically rolled back and what is left
     *             of the FlowFile is destroyed.
     */
    InputStream read(FlowFile flowFile);

    /**
     * Executes the given callback against the contents corresponding to the 在给定的FlowFile上执行指定的回调函数
     * given FlowFile.
     *
     * <i>Note</i>: The OutputStream provided to the given OutputStreamCallback
     * will not be accessible once this method has completed its execution.
     *
     * @param source flowfile to retrieve content of 从中获取内容的FlowFile
     * @param allowSessionStreamManagement allow session to hold the stream open for performance reasons 是否允许会话出于性能考虑一直打开流
     * @param reader that will be called to read the flowfile content 调用reader来读取内容
     * @throws IllegalStateException if detected that this method is being
     *             called from within a callback of another method in this session and for
     *             the given FlowFile(s)
     * @throws FlowFileHandlingException if the given FlowFile is already
     *             transferred or removed or doesn't belong to this session. Automatic
     *             rollback will occur.
     * @throws MissingFlowFileException if the given FlowFile content cannot be
     *             found. The FlowFile should no longer be reference, will be internally
     *             destroyed, and the session is automatically rolled back and what is left
     *             of the FlowFile is destroyed.
     * @throws FlowFileAccessException if some IO problem occurs accessing
     *             FlowFile content; if an attempt is made to access the InputStream
     *             provided to the given InputStreamCallback after this method completed its
     *             execution
     */
    void read(FlowFile source, boolean allowSessionStreamManagement, InputStreamCallback reader) throws FlowFileAccessException;

    /**
     * Combines the content of all given source FlowFiles into a single given 将所有给定FlowFile的内容合并到单个给定的FlowFile中。
     * destination FlowFile.
     *
     * @param sources the flowfiles to merge 需要合并的FlowFiles
     * @param destination the flowfile to use as the merged result 存储合并结果的FlowFile
     * @return updated destination FlowFile (new size, etc...)
     * @throws IllegalStateException if detected that this method is being
     * called from within a callback of another method in this session and for
     * the given FlowFile(s)
     * @throws IllegalArgumentException if the given destination is contained
     * within the sources
     * @throws FlowFileHandlingException if the given FlowFile is already
     * transferred or removed or doesn't belong to this session. Automatic
     * rollback will occur.
     * @throws MissingFlowFileException if the given FlowFile content cannot be
     * found. The FlowFile should no longer be reference, will be internally
     * destroyed, and the session is automatically rolled back and what is left
     * of the FlowFile is destroyed.
     * @throws FlowFileAccessException if some IO problem occurs accessing
     * FlowFile content. The state of the destination will be as it was prior to
     * this call.
     */
    FlowFile merge(Collection<FlowFile> sources, FlowFile destination);

    /**
     * Combines the content of all given source FlowFiles into a single given 将给定的所有FlowFile,合并到给定的目标FlowFile中
     * destination FlowFile.
     *
     * @param sources to merge together 需要合并的所有FlowFiles
     * @param destination to merge to 目标FlowFile
     * @param header bytes that will be added to the beginning of the merged 需要添加到合并后开始处的字节。可以是null或者空。
     * output. May be null or empty.
     * @param footer bytes that will be added to the end of the merged output. 需要添加到合并后结束处的字节。可以是null或者空。
     * May be null or empty.
     * @param demarcator bytes that will be placed in between each object merged 需要添加在合并对象之间的字节。可以是null或者空。
     * together. May be null or empty.
     * @return updated destination FlowFile (new size, etc...)
     * @throws IllegalStateException if detected that this method is being
     * called from within a callback of another method in this session and for
     * the given FlowFile(s)
     * @throws IllegalArgumentException if the given destination is contained
     * within the sources
     * @throws FlowFileHandlingException if the given FlowFile is already
     * transferred or removed or doesn't belong to this session. Automatic
     * rollback will occur.
     * @throws MissingFlowFileException if the given FlowFile content cannot be
     * found. The FlowFile should no longer be reference, will be internally
     * destroyed, and the session is automatically rolled back and what is left
     * of the FlowFile is destroyed.
     * @throws FlowFileAccessException if some IO problem occurs accessing
     * FlowFile content. The state of the destination will be as it was prior to
     * this call.
     */
    FlowFile merge(Collection<FlowFile> sources, FlowFile destination, byte[] header, byte[] footer, byte[] demarcator);

    /**
     * Executes the given callback against the content corresponding to the 对指定FlowFile的内容执行回调
     * given FlowFile.
     *
     * <i>Note</i>: The OutputStream provided to the given OutputStreamCallback
     * will not be accessible once this method has completed its execution.
     *
     * @param source to write to 需写入的源
     * @param writer used to write new content 用于写入新内容
     * @return updated FlowFile 更新后的FlowFile
     * @throws IllegalStateException if detected that this method is being
     * called from within a callback of another method in this session and for
     * the given FlowFile(s)
     * @throws FlowFileHandlingException if the given FlowFile is already
     * transferred or removed or doesn't belong to this session. Automatic
     * rollback will occur.
     * @throws MissingFlowFileException if the given FlowFile content cannot be
     * found. The FlowFile should no longer be referenced, will be internally
     * destroyed, and the session is automatically rolled back and what is left
     * of the FlowFile is destroyed.
     * @throws FlowFileAccessException if some IO problem occurs accessing
     * FlowFile content; if an attempt is made to access the OutputStream
     * provided to the given OutputStreamCallaback after this method completed
     * its execution
     */
    FlowFile write(FlowFile source, OutputStreamCallback writer) throws FlowFileAccessException;

    /**
     * Executes the given callback against the content corresponding to the 对指定FlowFile的内容执行回调
     * given flow file.
     *
     * <i>Note</i>: The InputStream & OutputStream provided to the given
     * StreamCallback will not be accessible once this method has completed its
     * execution.
     *
     * @param source to read from and write to 从中读取或者向其写入
     * @param writer used to read the old content and write new content 用于从中读取旧内容,写入新内容
     * @return updated FlowFile 更新后的FlowFile
     * @throws IllegalStateException if detected that this method is being
     * called from within a callback of another method in this session and for
     * the given FlowFile(s)
     * @throws FlowFileHandlingException if the given FlowFile is already
     * transferred or removed or doesn't belong to this session. Automatic
     * rollback will occur.
     * @throws MissingFlowFileException if the given FlowFile content cannot be
     * found. The FlowFile should no longer be reference, will be internally
     * destroyed, and the session is automatically rolled back and what is left
     * of the FlowFile is destroyed.
     * @throws FlowFileAccessException if some IO problem occurs accessing
     * FlowFile content; if an attempt is made to access the InputStream or
     * OutputStream provided to the given StreamCallback after this method
     * completed its execution
     */
    FlowFile write(FlowFile source, StreamCallback writer) throws FlowFileAccessException;

    /**
     * Executes the given callback against the content corresponding to the 对给定的FlowFile的内容执行回调,
     * given FlowFile, such that any data written to the OutputStream of the 这样一来任何写入到输出流
     * content will be appended to the end of FlowFile. 的数据会被追加到FlowFile的末尾。
     *
     * <i>Note</i>: The OutputStream provided to the given OutputStreamCallback 注意,传递给OutputStreamCallback的输出流
     * will not be accessible once this method has completed its execution. 在执行完成后不可访问。
     *
     * @param source the flowfile for which content should be appended
     * @param writer used to write new bytes to the flowfile content
     * @return the updated flowfile reference for the new content
     * @throws FlowFileAccessException if an attempt is made to access the
     * OutputStream provided to the given OutputStreamCallaback after this
     * method completed its execution
     */
    FlowFile append(FlowFile source, OutputStreamCallback writer) throws FlowFileAccessException;

    /**
     * Writes to the given FlowFile all content from the given content path. 将指定位置的内容写到给定的FlowFile中
     *
     * @param source the file from which content will be obtained
     * @param keepSourceFile if true the content is simply copied; if false the 如果是true,简单的复制内容;如果是false,
     * original content might be used in a destructive way for efficiency such 出于效率考虑,以有损的方式使用原始内容,这样一来
     * that the repository will have the data but the original data will be 仓库中会有数据,但是原始数据没有了。
     * gone. If false the source object will be removed or gone once imported. 如果是false,一旦导入结束,原始对象会被移除或者消失。
     * It will not be restored if the session is rolled back so this must be 回滚会话,也不会恢复,所以小心使用。
     * used with caution. In some cases it can result in tremendous efficiency 在某些场景中,可以获得巨大的效率提升,
     * gains but is also dangerous. 但是非常危险。
     * @param destination the FlowFile whose content will be updated
     * @return the updated destination FlowFile (new size)
     * @throws IllegalStateException if detected that this method is being
     * called from within a callback of another method in this session and for
     * the given FlowFile(s)
     * @throws FlowFileHandlingException if the given FlowFile is already
     * transferred or removed or doesn't belong to this session. Automatic
     * rollback will occur.
     * @throws MissingFlowFileException if the given FlowFile content cannot be
     * found. The FlowFile should no longer be reference, will be internally
     * destroyed, and the session is automatically rolled back and what is left
     * of the FlowFile is destroyed.
     * @throws FlowFileAccessException if some IO problem occurs accessing
     * FlowFile content
     */
    FlowFile importFrom(Path source, boolean keepSourceFile, FlowFile destination);

    /**
     * Writes to the given FlowFile all content from the given content path. 将指定位置的内容写到给定的FlowFile中
     *
     * @param source the file from which content will be obtained
     * @param destination the FlowFile whose content will be updated
     * @return the updated destination FlowFile (new size)
     * @throws IllegalStateException if detected that this method is being
     * called from within a callback of another method in this session and for
     * the given FlowFile(s)
     * @throws FlowFileHandlingException if the given FlowFile is already
     * transferred or removed or doesn't belong to this session. Automatic
     * rollback will occur.
     * @throws MissingFlowFileException if the given FlowFile content cannot be
     * found. The FlowFile should no longer be reference, will be internally
     * destroyed, and the session is automatically rolled back and what is left
     * of the FlowFile is destroyed.
     * @throws FlowFileAccessException if some IO problem occurs accessing
     * FlowFile content
     */
    FlowFile importFrom(InputStream source, FlowFile destination);

    /**
     * Writes the content of the given FlowFile to the given destination path. 将给定FlowFile的内容写到指定的位置
     *
     * @param flowFile to export the content of
     * @param destination to export the content to
     * @param append if true will append to the current content at the given 如果为true,会在指定位置的当前内容后追加;
     * path; if false will replace any current content 否则会替换任何当前内容
     * @throws IllegalStateException if detected that this method is being
     * called from within a callback of another method in this session and for
     * the given FlowFile(s)
     * @throws FlowFileHandlingException if the given FlowFile is already
     * transferred or removed or doesn't belong to this session. Automatic
     * rollback will occur.
     * @throws MissingFlowFileException if the given FlowFile content cannot be
     * found. The FlowFile should no longer be reference, will be internally
     * destroyed, and the session is automatically rolled back and what is left
     * of the FlowFile is destroyed.
     * @throws FlowFileAccessException if some IO problem occurs accessing
     * FlowFile content
     */
    void exportTo(FlowFile flowFile, Path destination, boolean append);

    /**
     * Writes the content of the given FlowFile to the given destination stream 将给定FlowFile的内容写入指定的输出流
     *
     * @param flowFile to export the content of
     * @param destination to export the content to
     * @throws IllegalStateException if detected that this method is being
     * called from within a callback of another method in this session and for
     * the given FlowFile(s)
     * @throws FlowFileHandlingException if the given FlowFile is already 给定的FlowFile已经转移了,移除了或者不属于这个会话。
     * transferred or removed or doesn't belong to this session. Automatic 会自动回滚。
     * rollback will occur.
     * @throws MissingFlowFileException if the given FlowFile content cannot be 无法找到FlowFile的内容。
     * found. The FlowFile should no longer be reference, will be internally 这样的FlowFile应不再引用,会内部销毁
     * destroyed, and the session is automatically rolled back and what is left 会话要自动回滚
     * of the FlowFile is destroyed. //FlowFile剩下的也会被销毁
     * @throws FlowFileAccessException if some IO problem occurs accessing 访问FlowFile内容时出现IO错误
     * FlowFile content
     */
    void exportTo(FlowFile flowFile, OutputStream destination);

    /**
     * Returns a ProvenanceReporter that is tied to this ProcessSession. 返回与当前会话绑定的ProvenanceReporter。
     *
     * @return the provenance reporter
     */
    ProvenanceReporter getProvenanceReporter();
}
